﻿using EPubFactory.TestHarness.Samples;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace EPubFactory.TestHarness
{
    /// <summary>Test harness for epubs.</summary>
    /// <remarks>
    /// Creates a sequence of epub archives to be inspected manually.
    /// </remarks>
    public class Program
    {
        #region Plumbing
        private const string WRITE_FOLDER = "Tests";

        private static readonly List<Task> _tasks = new List<Task>(25);

        /// <summary>Entry Point.</summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            InitFolder();

            Test("Trivial.epub", TrivialPackage);
            Test("TwoChapters.epub", TwoChaptersPackage);
            Test("TwoChaptersAndToc.epub", TwoChaptersAndTocPackage);

            Test("OnePageWithImage.epub", OnePageWithImage);

            WaitForCompletion();
        }

        private static void InitFolder()
        {
            if (!Directory.Exists(WRITE_FOLDER))
            {
                Directory.CreateDirectory(WRITE_FOLDER);
            }
            foreach (var filePath in Directory.GetFiles(WRITE_FOLDER))
            {
                File.Delete(filePath);
            }
            foreach (var dirPath in Directory.GetDirectories(WRITE_FOLDER))
            {
                Directory.Delete(dirPath, true);
            }
        }

        private static void Test(string path, Func<EPubWriter, Task> writerTest)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }
            if (writerTest == null)
            {
                throw new ArgumentNullException("writerTest");
            }

            _tasks.Add(PerformTest(path, writerTest));
        }

        private static async Task PerformTest(string path, Func<EPubWriter, Task> writerTest)
        {
            var subPath = Path.Combine(WRITE_FOLDER, path);
            var stream = File.Create(subPath);

            using (var writer = await EPubWriter.CreateWriterAsync(
                stream,
                "Test Pack",
                "Test Author",
                Guid.NewGuid().ToString()))
            {
                writer.Publisher = "Test App";

                await writerTest(writer).ConfigureAwait(false);
                await writer.WriteEndOfPackageAsync().ConfigureAwait(false);
            }
        }

        private static void WaitForCompletion()
        {
            Task.WaitAll(_tasks.ToArray());
        }
        #endregion

        #region Tests
        private static async Task TrivialPackage(EPubWriter writer)
        {
            await writer.AddChapterAsync("MyChapter.xhtml", "Only Chapter", Sample.TrivialChapter);
        }

        private static async Task TwoChaptersPackage(EPubWriter writer)
        {
            await writer.AddChapterAsync("FirstChapter.xhtml", "First Chapter", Sample.TrivialChapter);
            await writer.AddChapterAsync("SecondChapter.xhtml", "Second Chapter", Sample.TrivialChapter2);
        }

        private static async Task TwoChaptersAndTocPackage(EPubWriter writer)
        {
            await writer.AddChapterAsync("Toc.xhtml", "Table of Content", Sample.TocTwoChapters);
            await writer.AddChapterAsync("FirstChapter.xhtml", "First Chapter", Sample.TrivialChapter);
            await writer.AddChapterAsync("SecondChapter.xhtml", "Second Chapter", Sample.TrivialChapter2);
        }

        private static async Task OnePageWithImage(EPubWriter writer)
        {
            using (var imageStream =
                typeof(Program).Assembly.GetManifestResourceStream("EPubFactory.TestHarness.Samples.Spiral.jpg"))
            {
                using (var resourceStream = writer.GetResourceStream("Spiral.jpg", "image/jpeg"))
                {
                    await imageStream.CopyToAsync(resourceStream);
                }
                await writer.AddChapterAsync("MyChapter.html", "Only Chapter", Sample.TrivialWithImage);
            }
        }
        #endregion
    }
}